#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP) // 不敢使用sizeof()
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

// 添加报头
//  "x op y" -> "content_len"\r\n"x op y"\r\n
//  "exitcode result" -> "content_len"\r\n"exitcode result"\r\n
std::string enLength(const std::string &text)
{
    std::string send_string = std::to_string(text.size());
    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;
    return send_string;
}

// 取出正文
//  "content_len"\r\n"exitcode result"\r\n
bool deLength(const std::string &package, std::string *text)
{
    auto pos = package.find(LINE_SEP);
    if (pos == std::string::npos)
    {
        return false;
    }
    std::string text_len_str = package.substr(0, pos);
    int text_len = std::stoi(text_len_str);
    *text = package.substr(pos + LINE_SEP_LEN, text_len);
    std::cout<<"删除报头，取出正文："<<*text<<std::endl;
    return true;
}

// 没有人规定我们网络通信的时候，只能有一种协议！！
// 我们怎么让系统知道我们用的是哪一种协议呢？？
// "content_len"\r\n"协议编号"\r\n"x op y"\r\n

// 规定的请求正文结构
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char op)
        : _x(x), _y(y), _op(op)
    {
    }

    // 序列化 "x op y"
    bool serialize(std::string *out)
    {
        *out = "";
        std::string x_str = std::to_string(_x);
        std::string y_str = std::to_string(_y);
        *out += x_str;
        *out += SEP;
        *out += _op;
        *out += SEP;
        *out += y_str;
        return true;
    }

    // 反序列化 "x op y"
    bool deserialize(std::string &in)
    {
        auto left_pos = in.find(SEP);
        auto right_pos = in.rfind(SEP);
        if (left_pos == right_pos || left_pos == std::string::npos || right_pos == std::string::npos)
        {
            return false;
        }
        if (right_pos - (left_pos + SEP_LEN) != 1) // 确认操作符存在且为1
        {
            return false;
        }

        std::string x_str = in.substr(0, left_pos);
        std::string y_str = in.substr(right_pos + SEP_LEN);

        if (x_str.empty() || y_str.empty())
        {
            return false;
        }
        _x = std::stoi(x_str);
        _y = std::stoi(y_str);
        _op = in[left_pos + SEP_LEN];

        std::cout << "req反序列化：x:" << _x << " y:" << _y << " op:" << _op << std::endl;
        return true;
    }

    ~Request()
    {
    }

public:
    // "x op y"
    int _x;
    int _y;
    char _op;
};

// 规定的响应正文结构
class Response
{
public:
    Response()
    {
    }

    // 序列化 "ec res"
    bool serialize(std::string *out)
    {
        *out = "";
        *out += std::to_string(_exitcode);
        *out += SEP;
        *out += std::to_string(_result);
        return true;
    }

    // 反序列化
    bool deserialize(std::string &in)
    {
        std::cout<<"in"<<in<<std::endl;
        auto pos = in.find(SEP);
        if (pos == std::string::npos)
        {
            return false;
        }
        std::string ec_str = in.substr(0, pos);
        std::cout<<"ec_str"<<ec_str<<std::endl;
        std::string res_str = in.substr(pos + SEP_LEN);
         std::cout<<"res_str"<<res_str<<std::endl;
        if (ec_str.empty() || res_str.empty())
        {
            return false;
        }
        _exitcode = std::stoi(ec_str);
        _result = std::stoi(res_str);
        std::cout<<"_exitcode"<<_exitcode<<std::endl;
        std::cout<<"_result"<<_result<<std::endl;


        std::cout << "resp反序列化：res:" << _result << " ec:" << _exitcode << std::endl;
      
        return true;
    }

    ~Response()
    {
    }

public:
    int _exitcode; // 0：计算成功，!0表示计算失败，具体是多少，定好标准
    int _result;   // 计算结果
};

// "content_len"\r\n"x op y"\r\n"content_len"\r\n"x op y"\r\n"content_len"\r\n"x op
// 返回一个读取到的完整的规定格式的报文
// inbuffer 之前从sock读取信息的暂存缓冲区
bool recvPackage(int sock, std::string &inbuffer, std::string *pac)
{
    std::cout<<"进入读取报文函数"<<std::endl;
    // 1.接收
    char buffer[1024];
    // 2.判断接收到一个完整的报文
    while (true)
    {
        // 1.1.读取
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
         std::cout<<"从缓冲区读"<<std::endl;

        if (n > 0)//读到了
        {
         std::cout<<"读到了"<<std::endl;

            inbuffer += buffer;
            std::cout << "111处理前的inbuffer:\n" << inbuffer << std::endl;
           
            // 分析处理
            // 2.1.判断有无收到一个完整报头
            auto pos = inbuffer.find(LINE_SEP);
            std::cout<<"第一个分隔符下标"<<pos<<std::endl;
            if (pos == std::string::npos)
            {
                 std::cout << "没有完整报文\n" << inbuffer << std::endl;
                continue;
            }
            std::string text_len_string = inbuffer.substr(0, pos);
            std::cout<<"报头内容"<<text_len_string<<std::endl;
            if (text_len_string.empty())
            {
                 std::cout << "报文长度为空\n" << inbuffer << std::endl;
                continue;
            }
            // 2.2.判断有无收到一共完整正文
            int text_len = std::stoi(text_len_string);
            int pac_total_len = text_len_string.size() + 2 * LINE_SEP_LEN + text_len;
            if (inbuffer.size() < pac_total_len)
            {
                std::cout << "你输入的消息，没有严格遵守我们的协议，正在等待后续的内容, continue" << std::endl;
                continue;
            }
            // 2.3.把第一个完整报文从inbuffer中提取出，并在inbuffer中删除
            std::cout << "处理前的inbuffer:\n" << inbuffer << std::endl;
            *pac = inbuffer.substr(0, pac_total_len);
            inbuffer.erase(0, pac_total_len);
            std::cout << "处理后#inbuffer:\n " << inbuffer << std::endl;
            break;
        }
        else
        {
            //从sock中读取失败
            return false;
        }
    }
    return true;//一次只带一个完整报文
    
}

// bool recvRequestAll(int sock, std::vector<std::string> *out)
// {
//     std::string line;
//     while(recvRequest(sock, &line)) out->push_back(line);
// }
